www.gusucode.com > 基于Visual C++高级界面特效制作百例源码程序 > 基于Visual C++高级界面特效制作百例源码程序/code/char10/menu_button/MenuButton.cpp

    /* -----------------98/08/24 04:53AM-----------------
 *Uses code from CodeGuru.Com...
 *The niffy way of using the menu in immediate mode are (directly) from
 *  Using CMenu::TrackPopupMenu as an Immediate Function - Randy More ("http://www.codeguru.com/menu/track_popup.shtml"),
 *General ownerdraw format from
 *  Flat owner drawn buttons - Girish Bharadwaj ("http://www.codeguru.com/buttonctrl/flat_button.shtml"),
 *and the idea for drawing the arrow from
 *  PushButton with bitmap & text - Michael Santoro ("http://www.codeguru.com/buttonctrl/bitmap_text_button.shtml")
 *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * I have no way to test if this will work with UNICODE, however it _SHOULD_. (:
 * This was compiled with VC5 and MFC4.2. Tested on Win95 OSR2 (no IE4 integration).
 * This code should compile cleanly under warning level 4.
 *
 * To Use: Simply include "MenuButton.h" and "MenuButton.cpp" in your project,
 * and include "MenuButton.h" in whatever file you wish to use it in ("stdafx.h" mayhaps).
 *
 * Then in the dialog editor, make a normal button, a suggested size is 12x14. The
 * little arrow gfx will be centered in the button however.  Make a handler for
 * a button click, and copy the sample usage code to there, then of course modify to suit your needs.
 *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * Sample Usage Code:
//////////////////////////////////////////////////////////////////////////
//  //  //  //  //  //  //  //  //  //  //  //  //  //  //  //  //  //  //
//////////////////////////////////////////////////////////////////////////
//// -[Feral]---------------------------------------------------------------
//// pop up a menu, and add pre defined text to the edit ctrl.
//void CPP_Split::OnBUTTONNameFormatOptions()
//{
//    // -[Feral]-----------------------------------------------------------
//    // Vars and Assignment
//    CEdit *pEdit = (CEdit*)GetDlgItem(IDC_EDIT_NameFormat);
//
//
//    // -[Feral]-----------------------------------------------------------
//    // popup a menu and let the user make a selection...
//    DWORD dwSelectionMade = m_menubuttonNameFormatOptions.DoSingleClick(IDM_NameFormatOptions);
//
//    // -[Feral]-----------------------------------------------------------
//    // Do something with the selection
//    // -------------------------------------------------------------------
//    // The value of dwSelectionMade is the id of the command selected or 0 if no selection was made
//    switch(dwSelectionMade)
//    {
//        default:                        // Do nothing
//            break;
//        case `Menu Resource ID`:
//            pEdit->;ReplaceSel(_T("`Text to add at cursor, or replace selection with`") );
//            break;
//        case ID_PREDEFINEDPOPUP_SAMPLE1FILENAME1XEXTSPLITPIECE:       // "Sample #&1: Filename.1_X.Ext.SplitPiece",
//            pEdit->ReplaceSel(_T("<File>.<1_X>.<Ext>.SplitPiece") );
//            break;
//    }
//
//    // -[Feral]-----------------------------------------------------------
//    // Clean Up and Return
//}
//////////////////////////////////////////////////////////////////////////
//  //  //  //  //  //  //  //  //  //  //  //  //  //  //  //  //  //  //
//////////////////////////////////////////////////////////////////////////
 * --------------------------------------------------*/
// MenuButton.cpp : implementation file
//

#include "stdafx.h"
#include "File Axe.h"
#include "MenuButton.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMenuButton

CMenuButton::CMenuButton()
{
}

CMenuButton::~CMenuButton()
{
}


BEGIN_MESSAGE_MAP(CMenuButton, CButton)
	//{{AFX_MSG_MAP(CMenuButton)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMenuButton message handlers

DWORD CMenuButton::DoSingleClick(UINT uiIDMenuResource)
{
    // -[Feral]-----------------------------------------------------------
    // Vars and Assignment
    CMenu menu;
    int iMenuID = 0;
    DWORD dwSelectionMade;
    VERIFY(menu.LoadMenu(uiIDMenuResource) );

    CMenu *pmenuPopup = menu.GetSubMenu(iMenuID);
    ASSERT(pmenuPopup != NULL);
    POINT point;

    // -[Feral]-----------------------------------------------------------
    // get the point where the menu is to be displayed.
    // this is hte lower left corner of the control (button)
    CRect rect;
    GetWindowRect(rect);
    point.x = rect.left;
    point.y = rect.bottom;

    // -[Feral]-----------------------------------------------------------
    // show and track the menu
    dwSelectionMade = pmenuPopup->TrackPopupMenu( (TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_NONOTIFY|TPM_RETURNCMD),
                                                  point.x, point.y, this
                                                );
    // -[Feral]-----------------------------------------------------------
    // Clean Up and Return
    pmenuPopup->DestroyMenu();
    // The value of dwSelectionMade is the id of the command selected or 0 if no selection was made
    return dwSelectionMade;
}

void CMenuButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    // -[Feral]-----------------------------------------------------------
    // VALIDATION:
    ASSERT(lpDrawItemStruct != NULL);

    // -[Feral]-----------------------------------------------------------
    // Vars and Assignment
    CRect rect      = lpDrawItemStruct->rcItem;
    CDC *pDC        = CDC::FromHandle(lpDrawItemStruct->hDC);
    UINT uiState    = lpDrawItemStruct->itemState;
    CPen pen;
    CPen *ppenOld   = NULL;

    // -[Feral]-----------------------------------------------------------
    // set the pen color based on if we are disabled or not
    if( (uiState&ODS_DISABLED) )
    {
        pen.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_GRAYTEXT) );
    }
    else
    {
        pen.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNTEXT) );
    }


    // -[Feral]-----------------------------------------------------------
    // select the pen into the DC.
    ppenOld = pDC->SelectObject(&pen);


    // -[Feral]-----------------------------------------------------------
    // draw the border
    if( (uiState&ODS_SELECTED) )
    {
        pDC->DrawFrameControl(rect, DFC_BUTTON, DFCS_BUTTONPUSH|DFCS_PUSHED);
    }
    else
    {
        pDC->DrawFrameControl(rect, DFC_BUTTON, DFCS_BUTTONPUSH);
    }


    // -[Feral]-----------------------------------------------------------
    // Draw the Arrow...
    // Something like:
    // X
    // XX
    // XXX
    // XXXX
    // XXX
    // XX
    // X
    // In the Center of the button.
    CSize sizeArrow(4,7);
    CSize sizeOffsetTop(1,+1);          // size of the top stairsteps
    CSize sizeOffsetBottom(1,-1);       // size of the bottom stairsteps
    CPoint pointCenter( (rect.Width()/2), (rect.Height()/2) );
    CPoint pointStart( (pointCenter.x-(sizeArrow.cx/2) ), (pointCenter.y-(sizeArrow.cy/2) ) );
    CPoint pointStop ( (pointStart.x), (pointStart.y+sizeArrow.cy) );
    // -[Feral]-----------------------------------------------------------
    // start at the left and work to the right...
    for(int iInd=0; iInd<sizeArrow.cx; iInd++)
    {
        // -[Feral]-------------------------------------------------------
        // draw the lines
        pDC->MoveTo(pointStart);
        pDC->LineTo(pointStop);

        // -[Feral]-------------------------------------------------------
        // offset our points. (going right!)
        pointStart.Offset(sizeOffsetTop);
        pointStop .Offset(sizeOffsetBottom);
    }

    // -[Feral]-----------------------------------------------------------
    // Draw the focus rectangle if necessary.
    if( (uiState&ODS_FOCUS) )
    {
        CRect rectFocus(rect);
        rectFocus.DeflateRect(3,3);     // This looked prety close
        pDC->DrawFocusRect(rectFocus);
    }

    // -[Feral]-----------------------------------------------------------
    // Clean Up and Return
    pDC->SelectObject(ppenOld);         // Restore the pen
}

//
///EOF